<?php
/**
 * Created by PhpStorm.
 * User: BlueIdeaLirui
 * Date: 2019/11/11
 * Time: 10:13
 */

namespace business\bigdata\services\queues;

use business\base\caches\DataCache;
use business\bigdata\model\SupplierModel;
use business\bigdata\repositories\SupplierRepository;
use business\company\services\SupplierService;
use business\elasticsearch\models\BigDataSupplierModel;
use business\elasticsearch\repositories\BigdataSupplierRepository;
use common\queue\QueueConstants;
use common\utils\DateTimeUtils;

/**
 * 大数据供应商消费端服务
 * Class SupplierConsumerService
 * @package business\bigdata\services
 */
class SupplierConsumerService extends BaseService
{
    /**
     * @var array 大数据服务分类cache
     */
    protected $businessCache;

    /**
     * 指定模块
     */
    const MODULE = 'supplier';

    /**
     * 供应商消费端服务构造器
     * SupplierConsumerService constructor.
     */
    public function __construct()
    {
        $this->businessCache = SupplierRepository::getSupplierBusinessDictionary();
        $this->createIndex();
        parent::__construct();
    }

    /**
     * 创建索引
     * @return void
     */
    protected function createIndex()
    {
        $repository = new BigdataSupplierRepository();
        !$repository->existsIndex() && $repository->createIndex();
    }

    /**
     * 消费端实现
     * @throws \yii\base\InvalidConfigException
     */
    public function process
    (
        $values,
        $key,
        $messageId
    ) {
        $this->consumeQueue($this->callbackMethod, $values, $key, $messageId);
    }

    public function single(array $supplierId)
    {
        $supplierRepository = new SupplierRepository();
        $supplierBasics = $supplierRepository->getSupplierBasicInfoByIds($supplierId);
        $needUpdateIndexSuppliers = [];
        $needDeleteIndexSuppliers = [];
        $this->getSupplierDocumentArray($supplierBasics, $needUpdateIndexSuppliers, $needDeleteIndexSuppliers,
            $this->businessCache, $supplierRepository);
        $this->updateIndex($needUpdateIndexSuppliers, DateTimeUtils::now());
    }

    /**
     * 消费队列
     * @param callable $sucessedCallback
     * @return bool|mixed
     * @throws \yii\base\InvalidConfigException
     */
    protected function consumeQueue
    (
        callable $sucessedCallback,
        $values = '',
        $key = '',
        $messageId
    ) {
        $needUpdateIndexSuppliers = [];
        $needDeleteIndexSuppliers = [];

        $supplierRepository = new SupplierRepository();
        $dataCache          = new DataCache();

        $queueCacheName     = self::MODULE . '-' . QueueConstants::QUEUE_CHACHE_NAME;

        if ($dataCache->existsValue('consumer-' . $queueCacheName . ':' . $key
                , serialize(['values' => $values, 'created_on' => DateTimeUtils::now()])) == 1) {
            // 清除缓存记录
            $dataCache->delRecordByHash($queueCacheName, $key);

            $waitUpdateSupplierIds = explode(self::DELIMITER, $values);

            if (!empty($waitUpdateSupplierIds)) {
                $start = 0;
                $sizeCount = (self::MAX_COUNT_PER_INDEX / self::MAX_COUNT_PER_QUERY);

                while (1) {
                    $start++;

                    $startTime = explode(' ', microtime());

                    $slicceUpdateSupplierIds = array_slice($waitUpdateSupplierIds, ($start - 1) * $sizeCount, $sizeCount);

                    if (!empty($slicceUpdateSupplierIds)) {
                        $supplierBasics = $supplierRepository->getSupplierBasicInfoByIds($slicceUpdateSupplierIds);
                        if (is_array($supplierBasics)) {
                            $basicIds = array_column($supplierBasics, 'id');
                            // 判断是否有删除的供应商数据
                            foreach ($slicceUpdateSupplierIds as $id) {
                                if (!in_array($id, $basicIds)) {
                                    array_push($needDeleteIndexSuppliers, $id);
                                }
                            }
                        }

                        $this->getSupplierDocumentArray($supplierBasics, $needUpdateIndexSuppliers, $needDeleteIndexSuppliers,
                            $this->businessCache, $supplierRepository);

                        $endTime = explode(' ', microtime());
                        $thisTime = $endTime[0] + $endTime[1] - ($startTime[0] + $startTime[1]);
                        echo "大数据供应商-增量索引更新：每" . $sizeCount . "条记录执行数据拼接耗时：" . round($thisTime, 3) . " 秒" . PHP_EOL;

                        //每x次轮训刷新一次搜索引擎
                        if ($start % $sizeCount == 0
                            && (!empty($needUpdateIndexSuppliers) || !empty($needDeleteIndexSuppliers))
                        ) {
                            //刷新搜索引擎
                            $this->updateDataIndex($needUpdateIndexSuppliers, 'update');
                            $this->updateDataIndex($needDeleteIndexSuppliers, 'delete');

                            $needUpdateIndexSuppliers = [];
                            $needDeleteIndexSuppliers = [];
                        }
                    } else {
                        // 清除缓存记录
                        $dataCache->delRecordByHash($queueCacheName, $key);
                        break;
                    }
                }
            }

            // 防止最后的未更新
            $this->updateDataIndex($needUpdateIndexSuppliers, 'update');
            $this->updateDataIndex($needDeleteIndexSuppliers, 'delete');

            // 清除缓存记录
            $dataCache->delRecordByHash($queueCacheName, $key);

            if (is_callable($sucessedCallback)) {
                return call_user_func($sucessedCallback, $needUpdateIndexSuppliers);
            }

            return true;
        }

        return true;
    }

    /**
     * 获取供应商索引document
     * @param $supplierBasics
     * @param $needUpdateIndexSuppliers
     * @param array $needDeleteIndexSuppliers
     * @param $businessCache
     */
    protected function getSupplierDocumentArray
    (
        $supplierBasics,
        & $needUpdateIndexSuppliers,
        & $needDeleteIndexSuppliers = [],
        $businessCache,
        $repository
    ) {
        $supplierRepository = (!empty($repository)) ? $repository : (new SupplierRepository());

        // supplierNames数组
        $supplierNames = array_column($supplierBasics, 'name');
        // 获取项目案例
        $supplierProjects = $supplierRepository->getProjectCaseBySupplerNames($supplierNames);
        // 获取服务资质
        $supplierQualifications = $supplierRepository->getQualificationBySupplierNames($supplierNames);

        // supplierIds数组
        $supplierIds = array_column($supplierBasics, 'id');

        // 获取百强合作企业数据
        $topDevelopers = $supplierRepository->getTopDeveloperBySupplerIds($supplierIds);
        // 获取top级标签
        $topBusinessAreas = $supplierRepository->getTopBusinessAreaSupplierIds($supplierIds);
        // 获取榜上有名数据
        $boardList = $supplierRepository->getBoardListBySupplerIds($supplierIds);

        if (!empty($supplierBasics)) {
            foreach ($supplierBasics as $basic) {
                $model = new SupplierModel();
                $model->fill($basic);
                $model->cooperationDevelopersNumber = $supplierRepository->getCooperationDevelopersNumberById($model->supplierId);
                $model->qualificationNumber = count($supplierRepository->getQualificationByName($model->supplierName));
                $model->memberNumber = $supplierRepository->getMemberNumberByName($model->supplierName);
                $model->linkNumber = $supplierRepository->getLinkNumber($model->supplierId);

                // 项目案例
                if (!empty($supplierProjects)) {
                    foreach ($supplierProjects as $project) {
                        if ($project['name'] == $model->supplierName) {
                            array_push($model->supplierProjectCase, $project['project_name']);
                            $model->supplierProjectCaseNumber++;    //跟产品确认source为0/1都要
                        }
                    }
                }

                // 是否案例丰富
                if (count($model->supplierProjectCase) > 9) {
                    $model->hasRichcase = 1;
                } else {
                    $model->hasRichcase = 0;
                }

                // 获取百强合作企业数据
                if (!empty($topDevelopers)) {
                    foreach ($topDevelopers as $topDeveloper){
                        if($model->supplierId == $topDeveloper['supplier_id']){
                            array_push($model->topDeveloper, $topDeveloper['name']);
                        }
                    }
                }

                // 获取top级标签
                if (!empty($topBusinessAreas)) {
                    foreach ($topBusinessAreas as $topBusinessArea){
                        if($model->supplierId == $topBusinessArea['supplier_id']){
                            array_push($model->topBusinessArea, $topBusinessArea['business_area']);
                        }
                    }
                }

                // 获取榜上余名数据
                if (!empty($boardList)) {
                    foreach ($boardList as $board){
                        if($model->supplierId == $board['supplier_id']){
                            array_push($model->boardList, json_encode(['name'=>$board['name'],'url'=>$board['url']]));
                        }
                    }
                }

                // 上榜个数
                $model->boardCout = count($model->boardList);

                // 服务资质
                if (!empty($supplierQualifications)) {
                    foreach ($supplierQualifications as $qualification) {
                        if ($qualification['name'] == $model->supplierName) {
                            array_push($model->supplierQualificationName, $qualification['qualification_name']);
                            array_push($model->supplierQualificationCode,
                                $qualification['qualification_code'] . '-' . $qualification['level_code']);
                            $model->customProperty['supplierQualification_' . $qualification['qualification_code']] = $qualification['level_code'];
                        }
                    }
                }

                // 产品分类信息
                if (is_array($model->supplierBusinessCode3)) {
                    foreach ($model->supplierBusinessCode3 as $code3) {
                        if (isset($businessCache[$code3])) {
                            array_push($model->supplierBusinessCode1,
                                $businessCache[$code3]['one_cate_code']);
                            array_push($model->supplierBusinessName1,
                                $businessCache[$code3]['one_cate_name']);
                            array_push($model->supplierBusinessCode2,
                                $businessCache[$code3]['two_cate_code']);
                            array_push($model->supplierBusinessName2,
                                $businessCache[$code3]['two_cate_name']);
                            array_push($model->supplierBusinessName3,
                                $businessCache[$code3]['three_cate_name']);
                        }
                    }
                }

                // 校验条件
                if ($model->checkCondition()) {
                    array_push($needUpdateIndexSuppliers, $model);
                } else {
                    array_push($needDeleteIndexSuppliers, $model->supplierId);
                }
            }
        }
    }

    /**
     * 处理需要更新的大数据供应商数据
     * @param $needUpdateIndex
     * @param $repository \business\company\repositories\SupplierRepository
     * @param $service SupplierService
     * @return array
     */
    protected function handleUpdateSet
    (
        $needUpdateIndex,
        $repository
    ) {

        if (!empty($needUpdateIndex)) {
            $supplierBasicInfo = $repository->getSupplierBasicInfoByCompanyName($needUpdateIndex['supplierName']);
            // 如果平台供应商存在则选择平台数据
            if (!empty($supplierBasicInfo)) {
                $supplierId = $supplierBasicInfo['supplier_id'];
                $needUpdateIndex['companySupplierId'] = $supplierId;
            } else {
                $needUpdateIndex['companySupplierId'] = '';
            }
        }
        return $needUpdateIndex;
    }

    /**
     * 更新索引
     * @param array $needUpdateIndexArrays
     * @param $jobCreatedTime
     */
    protected function updateIndex
    (
        $needUpdateIndexArrays = [],
        $jobCreatedTime
    ) {
        if (!empty($needUpdateIndexArrays)) {
            $indexStartTime = explode(' ', microtime());

            $repository = new \business\company\repositories\SupplierRepository();

            foreach ($needUpdateIndexArrays as $needUpdateIndex) {
                $supplierId  = $needUpdateIndex->supplierId;
                $supplierName = $needUpdateIndex->supplierName;

                $id = md5($supplierName);

                try {
                    $supplierEsModel = BigDataSupplierModel::findOne($id);

                    if (empty($supplierEsModel)) {
                        $supplierEsModel = new BigDataSupplierModel();
                        $supplierEsModel->primaryKey = md5($supplierName);
                    }

                    $supplierEsModel->setAttributes(
                        $this->handleUpdateSet($needUpdateIndex->toArray(), $repository), false
                    );

                    $supplierEsModel->indexCreatedTime = !empty($jobCreatedTime)
                        ? $jobCreatedTime :date('Y-m-d H:i:s');

                    $rs = $supplierEsModel->save();

                    if (!$rs) {
                        \Yii::error('update es_supplier failed! supplier_id:' . $supplierId);
                    }
                    echo 'success supplier_id is ' . $supplierId . PHP_EOL;
                } catch (\Exception $e) {
                    echo 'update failed! supplier_id:' . $supplierId . PHP_EOL;
                    $title = isset($supplierName) ? $supplierName : '';
                    $this->saveUnIndexData('es_big_data_supplier', $title, $supplierId, $e);
                }
            }

            $indexEndTime = explode(' ', microtime());
            $indexThisTime = $indexEndTime[0] + $indexEndTime[1] - ($indexStartTime[0] + $indexStartTime[1]);
            $indexThisTime = round($indexThisTime, 3);
            echo  "update索引耗时：" . $indexThisTime . " 秒" . PHP_EOL;
        }
    }

    /**
     * 删除索引
     * @param array $needDeleteIndexArrays
     * @param $jobCreatedTime
     * @throws \yii\elasticsearch\Exception
     */
    protected function deleteIndex
    (
        $needDeleteIndexArrays = [],
        $jobCreatedTime
    ) {
        if (!empty($needDeleteIndexArrays)) {
            $indexStartTime = explode(' ', microtime());
            $supplierRepository = new SupplierRepository();
            foreach ($needDeleteIndexArrays as $supplierId) {
                $companyName = $supplierRepository->getSupplierNameByIds($supplierId);

                $id = md5($companyName);

                try{
                    $supplierEsModel = BigDataSupplierModel::findOne($id);

                    if ($supplierEsModel) {
                        $rs = $supplierEsModel->deleteAll(['_id' => $id]);

                        if (!$rs) {
                            \Yii::error('delete es_supplier failed! supplier_id:' . $supplierId);
                        }
                        echo 'success supplier_id is ' . $supplierId . PHP_EOL;
                    }

                } catch (\Exception $e) {
                    echo 'delete failed! supplier_id:' . $supplierId . PHP_EOL;
                    $title = isset($companyName) ? $companyName : '';
                    $this->saveUnIndexData('es_supplier', $title, $supplierId, $e);
                }
            }

            $indexEndTime = explode(' ', microtime());
            $indexThisTime = $indexEndTime[0] + $indexEndTime[1] - ($indexStartTime[0] + $indexStartTime[1]);
            $indexThisTime = round($indexThisTime, 3);
            echo "  删除索引耗时：" . $indexThisTime . " 秒" . PHP_EOL;
        }
    }
}
